package com.datagateway.component;

import com.datagateway.config.DataGatewayProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 告警管理器组件
 * 负责系统异常监控和告警通知
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class AlertManager {

    private static final Logger logger = LoggerFactory.getLogger(AlertManager.class);

    @Autowired(required = false)
    private JavaMailSender mailSender;

    @Autowired
    private DataGatewayProperties properties;

    /**
     * 告警队列
     */
    private final BlockingQueue<Alert> alertQueue = new LinkedBlockingQueue<>();

    /**
     * 告警统计
     */
    private final AtomicLong totalAlerts = new AtomicLong(0);
    private final AtomicLong sentAlerts = new AtomicLong(0);
    private final AtomicLong failedAlerts = new AtomicLong(0);

    /**
     * 告警级别枚举
     */
    public enum AlertLevel {
        INFO, WARN, ERROR, CRITICAL
    }

    /**
     * 告警类型枚举
     */
    public enum AlertType {
        SYSTEM_ERROR,      // 系统错误
        DATA_PROCESSING,   // 数据处理错误
        KAFKA_CONSUMER,    // Kafka消费者错误
        HIVE_WRITER,       // Hive写入错误
        RETRY_QUEUE,       // 重试队列告警
        MEMORY_USAGE,      // 内存使用告警
        PERFORMANCE,       // 性能告警
        MEMORY_LEAK        // 内存泄漏
    }

    /**
     * 发送告警
     * 
     * @param level 告警级别
     * @param type 告警类型
     * @param title 告警标题
     * @param message 告警消息
     * @param details 详细信息
     */
    public void sendAlert(AlertLevel level, AlertType type, String title, String message, String details) {
        Alert alert = new Alert(level, type, title, message, details);
        
        try {
            alertQueue.offer(alert);
            totalAlerts.incrementAndGet();
            
            // 异步处理告警
            processAlertAsync(alert);
            
        } catch (Exception e) {
            logger.error("发送告警失败: {}", title, e);
        }
    }

    /**
     * 设置邮件告警启用状态
     * 
     * @param mailEnabled 是否启用邮件告警
     */
    public void setMailEnabled(boolean mailEnabled) {
        this.mailEnabled = mailEnabled;
        logger.info("邮件告警状态已更新: {}", mailEnabled);
    }

    /**
     * 重新初始化邮件服务
     */
    public void reinitializeMailService() {
        try {
            // 重新初始化邮件配置
            initMailService();
            logger.info("邮件服务已重新初始化");
        } catch (Exception e) {
            logger.error("重新初始化邮件服务失败", e);
        }
    }

    /**
     * 发送内存泄漏告警
     * 
     * @param leakType 泄漏类型
     * @param message 告警消息
     */
    public void sendMemoryLeakAlert(String leakType, String message) {
        sendAlert(AlertLevel.WARNING, AlertType.MEMORY_LEAK, 
                 "内存泄漏告警", leakType + ": " + message, "");
    }

    /**
     * 发送系统错误告警
     * 
     * @param error 错误信息
     * @param details 详细信息
     */
    public void sendSystemErrorAlert(String error, String details) {
        sendAlert(AlertLevel.ERROR, AlertType.SYSTEM_ERROR, 
                 "系统错误告警", error, details);
    }

    /**
     * 发送数据处理错误告警
     * 
     * @param error 错误信息
     * @param dataId 数据ID
     */
    public void sendDataProcessingAlert(String error, String dataId) {
        sendAlert(AlertLevel.WARN, AlertType.DATA_PROCESSING, 
                 "数据处理错误", error, "数据ID: " + dataId);
    }

    /**
     * 发送Kafka消费者错误告警
     * 
     * @param error 错误信息
     * @param topic 主题名称
     */
    public void sendKafkaConsumerAlert(String error, String topic) {
        sendAlert(AlertLevel.ERROR, AlertType.KAFKA_CONSUMER, 
                 "Kafka消费者错误", error, "主题: " + topic);
    }

    /**
     * 发送Hive写入错误告警
     * 
     * @param error 错误信息
     * @param batchSize 批次大小
     */
    public void sendHiveWriterAlert(String error, int batchSize) {
        sendAlert(AlertLevel.ERROR, AlertType.HIVE_WRITER, 
                 "Hive写入错误", error, "批次大小: " + batchSize);
    }

    /**
     * 发送重试队列告警
     * 
     * @param retryCount 重试次数
     * @param deadLetterCount 死信数量
     */
    public void sendRetryQueueAlert(long retryCount, long deadLetterCount) {
        if (deadLetterCount > 100) {
            sendAlert(AlertLevel.CRITICAL, AlertType.RETRY_QUEUE, 
                     "死信队列告警", "死信队列数据过多", 
                     "死信数量: " + deadLetterCount + ", 重试次数: " + retryCount);
        } else if (retryCount > 1000) {
            sendAlert(AlertLevel.WARN, AlertType.RETRY_QUEUE, 
                     "重试队列告警", "重试次数过多", 
                     "重试次数: " + retryCount + ", 死信数量: " + deadLetterCount);
        }
    }

    /**
     * 发送内存使用告警
     * 
     * @param usedMemory 已使用内存
     * @param maxMemory 最大内存
     * @param usagePercent 使用百分比
     */
    public void sendMemoryUsageAlert(long usedMemory, long maxMemory, double usagePercent) {
        if (usagePercent > 90) {
            sendAlert(AlertLevel.CRITICAL, AlertType.MEMORY_USAGE, 
                     "内存使用告警", "内存使用率过高", 
                     String.format("使用率: %.2f%%, 已使用: %d MB, 最大: %d MB", 
                                  usagePercent, usedMemory / 1024 / 1024, maxMemory / 1024 / 1024));
        } else if (usagePercent > 80) {
            sendAlert(AlertLevel.WARN, AlertType.MEMORY_USAGE, 
                     "内存使用告警", "内存使用率较高", 
                     String.format("使用率: %.2f%%, 已使用: %d MB, 最大: %d MB", 
                                  usagePercent, usedMemory / 1024 / 1024, maxMemory / 1024 / 1024));
        }
    }

    /**
     * 发送性能告警
     * 
     * @param metric 性能指标
     * @param value 指标值
     * @param threshold 阈值
     */
    public void sendPerformanceAlert(String metric, double value, double threshold) {
        sendAlert(AlertLevel.WARN, AlertType.PERFORMANCE, 
                 "性能告警", metric + "超过阈值", 
                 String.format("%s: %.2f, 阈值: %.2f", metric, value, threshold));
    }

    /**
     * 异步处理告警
     * 
     * @param alert 告警对象
     */
    private void processAlertAsync(Alert alert) {
        try {
            // 记录告警日志
            logAlert(alert);
            
            // 发送邮件告警
            if (mailSender != null && isCriticalAlert(alert)) {
                sendEmailAlert(alert);
            }
            
            sentAlerts.incrementAndGet();
            
        } catch (Exception e) {
            logger.error("处理告警失败: {}", alert.getTitle(), e);
            failedAlerts.incrementAndGet();
        }
    }

    /**
     * 记录告警日志
     * 
     * @param alert 告警对象
     */
    private void logAlert(Alert alert) {
        String logMessage = String.format("[%s] %s - %s: %s", 
                                         alert.getLevel(), alert.getType(), 
                                         alert.getTitle(), alert.getMessage());
        
        switch (alert.getLevel()) {
            case CRITICAL:
            case ERROR:
                logger.error(logMessage);
                break;
            case WARN:
                logger.warn(logMessage);
                break;
            case INFO:
            default:
                logger.info(logMessage);
                break;
        }
        
        if (alert.getDetails() != null && !alert.getDetails().isEmpty()) {
            logger.debug("告警详情: {}", alert.getDetails());
        }
    }

    /**
     * 发送邮件告警
     * 
     * @param alert 告警对象
     */
    private void sendEmailAlert(Alert alert) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setTo("admin@datagateway.com"); // 配置告警邮箱
            message.setSubject(String.format("[%s] %s", alert.getLevel(), alert.getTitle()));
            
            StringBuilder content = new StringBuilder();
            content.append("告警时间: ").append(alert.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("\n");
            content.append("告警级别: ").append(alert.getLevel()).append("\n");
            content.append("告警类型: ").append(alert.getType()).append("\n");
            content.append("告警标题: ").append(alert.getTitle()).append("\n");
            content.append("告警消息: ").append(alert.getMessage()).append("\n");
            if (alert.getDetails() != null && !alert.getDetails().isEmpty()) {
                content.append("详细信息: ").append(alert.getDetails()).append("\n");
            }
            content.append("\n请及时处理相关问题。");
            
            message.setText(content.toString());
            
            mailSender.send(message);
            logger.info("邮件告警发送成功: {}", alert.getTitle());
            
        } catch (Exception e) {
            logger.error("发送邮件告警失败: {}", alert.getTitle(), e);
            throw e;
        }
    }

    /**
     * 判断是否为严重告警
     * 
     * @param alert 告警对象
     * @return true如果是严重告警
     */
    private boolean isCriticalAlert(Alert alert) {
        return alert.getLevel() == AlertLevel.CRITICAL || alert.getLevel() == AlertLevel.ERROR;
    }

    /**
     * 获取告警统计信息
     * 
     * @return 告警统计信息
     */
    public AlertStatistics getAlertStatistics() {
        return new AlertStatistics(
            totalAlerts.get(),
            sentAlerts.get(),
            failedAlerts.get(),
            alertQueue.size()
        );
    }

    /**
     * 告警内部类
     */
    public static class Alert {
        private final AlertLevel level;
        private final AlertType type;
        private final String title;
        private final String message;
        private final String details;
        private final LocalDateTime timestamp;

        public Alert(AlertLevel level, AlertType type, String title, String message, String details) {
            this.level = level;
            this.type = type;
            this.title = title;
            this.message = message;
            this.details = details;
            this.timestamp = LocalDateTime.now();
        }

        // Getter方法
        public AlertLevel getLevel() { return level; }
        public AlertType getType() { return type; }
        public String getTitle() { return title; }
        public String getMessage() { return message; }
        public String getDetails() { return details; }
        public LocalDateTime getTimestamp() { return timestamp; }
    }

    /**
     * 告警统计信息类
     */
    public static class AlertStatistics {
        private final long totalAlerts;
        private final long sentAlerts;
        private final long failedAlerts;
        private final int pendingAlerts;

        public AlertStatistics(long totalAlerts, long sentAlerts, long failedAlerts, int pendingAlerts) {
            this.totalAlerts = totalAlerts;
            this.sentAlerts = sentAlerts;
            this.failedAlerts = failedAlerts;
            this.pendingAlerts = pendingAlerts;
        }

        // Getter方法
        public long getTotalAlerts() { return totalAlerts; }
        public long getSentAlerts() { return sentAlerts; }
        public long getFailedAlerts() { return failedAlerts; }
        public int getPendingAlerts() { return pendingAlerts; }
        public double getSuccessRate() { 
            return totalAlerts > 0 ? (double) sentAlerts / totalAlerts * 100 : 0; 
        }

        @Override
        public String toString() {
            return String.format("AlertStatistics{totalAlerts=%d, sentAlerts=%d, " +
                               "failedAlerts=%d, pendingAlerts=%d, successRate=%.2f%%}",
                               totalAlerts, sentAlerts, failedAlerts, pendingAlerts, getSuccessRate());
        }
    }
}
